/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. This program is distributed
* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.hq.authz.server.session;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.hibernate.type.IntegerType;
import org.hyperic.hibernate.dialect.HQDialect;
import org.hyperic.hq.appdef.shared.AppdefEntityConstants;
import org.hyperic.hq.authz.shared.AuthzConstants;
import org.hyperic.hq.dao.HibernateDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class ResourceEdgeDAO
extends HibernateDAO<ResourceEdge> {
@Autowired
ResourceEdgeDAO(SessionFactory f) {
super(ResourceEdge.class, f);
}
ResourceEdge create(Resource from, Resource to, int distance, ResourceRelation relation) {
ResourceEdge res = new ResourceEdge(from, to, distance, relation);
save(res);
return res;
}
Map findDescendantMap(Resource r) {
String sql = "select e.to, e.distance from ResourceEdge e " + "where e.from = :from "
+ "and distance > :distance";
List vals = getSession().createQuery(sql).setParameter("from", r).setInteger("distance", 0)
.list();
return convertDistanceListToMap(vals);
}
Map convertDistanceListToMap(List vals) {
Map res = new HashMap();
for (Iterator i = vals.iterator(); i.hasNext();) {
Object[] ent = (Object[]) i.next();
Resource r = (Resource) ent[0];
Integer distance = (Integer) ent[1];
Collection c = (Collection) res.get(distance);
if (c == null) {
c = new ArrayList();
res.put(distance, c);
}
c.add(r);
}
return res;
}
/**
* @return {@link Collection} of {@link ResourceEdge}s
*/
@SuppressWarnings("unchecked")
Collection<ResourceEdge> findChildEdges(List<Resource> resources, ResourceRelation rel) {
String sql = "from ResourceEdge e " +
"where e.from in (:resources) " +
"and distance = 1 " +
"and rel_id = :rel_id ";
final List<ResourceEdge> rtn = new ArrayList<ResourceEdge>(resources.size());
final Query query = getSession().createQuery(sql);
int size = resources.size();
for (int i = 0; i < size; i += BATCH_SIZE) {
int end = Math.min(i + BATCH_SIZE, size);
final List<ResourceEdge> edges =
query.setParameterList("resources", resources.subList(i, end))
.setInteger("rel_id", rel.getId().intValue())
.list();
rtn.addAll(edges);
}
return rtn;
}
/**
* @return {@link Collection} of {@link ResourceEdge}s
*/
@SuppressWarnings("unchecked")
Collection<ResourceEdge> findDescendantEdges(List<Resource> resources, ResourceRelation rel) {
String sql = "from ResourceEdge e " + "where e.from in (:resources) "
+ "and distance > :distance " + "and rel_id = :rel_id ";
List<ResourceEdge> rtn = new ArrayList<ResourceEdge>();
Query query = getSession().createQuery(sql);
int size = resources.size();
for (int i = 0; i < size; i += BATCH_SIZE) {
int end = Math.min(i + BATCH_SIZE, size);
rtn.addAll(query.setParameterList("resources", resources.subList(i, end)).setInteger(
"distance", 0).setInteger("rel_id", rel.getId().intValue()).list());
}
return rtn;
}
/**
* @return {@link Collection} of {@link ResourceEdge}s
*/
Collection<ResourceEdge> findDescendantEdges(Resource r, ResourceRelation rel) {
return findDescendantEdges(Collections.singletonList(r), rel);
}
List<ResourceEdge> findDescendantEdgesByNetworkRelation(Integer resourceId,
List<Integer> platformTypeIds,
String platformName) {
String nameEx = null;
String sql = "select {e.*} from EAM_RESOURCE_EDGE e " +
" join EAM_RESOURCE r on e.to_id = r.id " +
" join EAM_PLATFORM p on p.resource_id = r.id " + " where e.rel_id = " +
AuthzConstants.RELATION_NETWORK_ID + " and e.distance != 0 ";
if (resourceId != null) {
sql += " and r.id = :rid ";
}
if (platformTypeIds != null && !platformTypeIds.isEmpty()) {
sql += " and p.platform_type_id in (:ptids) ";
}
if (platformName != null && platformName.trim().length() > 0) {
HQDialect dialect = getHQDialect();
nameEx = dialect.getRegExSQL("r.sort_name", ":regex", true, false);
sql += " and (" + nameEx + ") ";
}
sql += " order by r.sort_name ";
Query query = getSession().createSQLQuery(sql).addEntity("e", ResourceEdge.class);
if (resourceId != null) {
query.setInteger("rid", resourceId.intValue());
}
if (platformTypeIds != null && !platformTypeIds.isEmpty()) {
query.setParameterList("ptids", platformTypeIds, new IntegerType());
}
if (nameEx != null) {
query.setString("regex", platformName);
}
return query.list();
}
@SuppressWarnings("unchecked")
Collection<ResourceEdge> findAncestorEdges(Resource r, ResourceRelation rel) {
String sql = "from ResourceEdge e where e.from = :from and distance < :distance and rel_id = :rel_id ";
return getSession().createQuery(sql).setParameter("from", r).setInteger("distance", 0)
.setInteger("rel_id", rel.getId().intValue()).list();
}
void deleteEdges(Resource r) {
String sql = "from ResourceEdge where to_id = :to or from_id = :from)";
@SuppressWarnings("unchecked")
List<ResourceEdge> edges = getSession().createQuery(sql).setParameter("to", r).setParameter("from", r).list();
for (ResourceEdge edge : edges) {
remove(edge);
}
}
void deleteEdges(Resource r, ResourceRelation rel) {
String sql = "from ResourceEdge where (to_id = :to or from_id = :from) and rel_id = :rel_id ";
@SuppressWarnings("unchecked")
List<ResourceEdge> edges = getSession().createQuery(sql)
.setParameter("to", r)
.setParameter("from", r)
.setInteger("rel_id", rel.getId())
.list();
for (ResourceEdge edge : edges) {
remove(edge);
}
}
void deleteEdge(Resource parent, Resource child, ResourceRelation rel) {
String sql = "from ResourceEdge where from_id = :from and to_id = :to and rel_id = :rel_id ";
@SuppressWarnings("unchecked")
List<ResourceEdge> edges = getSession().createQuery(sql)
.setParameter("from", parent)
.setParameter("to", child)
.setInteger("rel_id", rel.getId())
.list();
for (ResourceEdge edge : edges) {
remove(edge);
}
}
@SuppressWarnings("unchecked")
Collection<ResourceEdge> getDescendantEdgesOfType(Collection<Resource> resources, Resource prototype,
ResourceRelation relation, int distance) {
String sign = (distance < 0) ? "<=" : ">=";
distance = Math.abs(distance);
final StringBuilder hqlbuf = new StringBuilder(64)
.append("FROM ResourceEdge re ")
.append("WHERE distance ").append(sign).append(" :dist and relation=:relation ")
.append("AND re.from in (:from)");
if (prototype != null) {
hqlbuf.append(" AND re.to.prototype = :type");
}
final String hql = hqlbuf.toString();
final Query query = getSession()
.createQuery(hql)
.setParameterList("from", resources)
.setParameter("relation", relation)
.setParameter("dist", distance);
if (prototype != null) {
query.setParameter("type", prototype);
}
return query.list();
}
// Retrieve the parent of a given resource, if one exists, otherwise return
// null
ResourceEdge getParentEdge(Resource resource, ResourceRelation relation) {
String hql = "from ResourceEdge re where re.from=:from and distance=-1 and relation=:relation";
Iterator iterator = getSession()
.createQuery(hql)
.setParameter("from", resource)
.setParameter("relation", relation)
.iterate();
if (iterator.hasNext()) {
return (ResourceEdge) iterator.next();
}
return null;
}
// Retrieve the children of a given resource, base on the relation
List<ResourceEdge> findChildEdges(Resource resource, ResourceRelation relation) {
String hql = "from ResourceEdge re "
+ "where re.from=:from and distance=1 and relation=:relation";
return getSession().createQuery(hql).setParameter("from", resource).setParameter(
"relation", relation).list();
}
List<ResourceEdge> findByName(String name, ResourceRelation relation) {
return getSession().createCriteria(ResourceEdge.class).createAlias("from", "f").add(
Restrictions.ilike("f.name", name, MatchMode.ANYWHERE)).add(
Restrictions.eq("relation", relation)).add(Restrictions.eq("distance", new Integer(0)))
.list();
}
// Returns the number of descendants of a given resource
int getDescendantCount(Resource resource, ResourceRelation relation) {
String hql = "select count(re) from ResourceEdge re "
+ "where re.from=:from and distance > 0 and relation=:relation";
return ((Number) getSession().createQuery(hql).setParameter("from", resource)
.setParameter("relation", relation).iterate().next()).intValue();
}
// Checks whether or not a given resource has a value to=from
boolean hasSelfEdge(Resource resource) {
String sql = "from ResourceEdge where from_id = :from and from_id = to_id";
@SuppressWarnings("unchecked")
int size = getSession().createQuery(sql).setInteger("from", resource.getId()).list().size();
if (size>0){
return true;
}
return false;
}
// Checks whether or not a given resource has a relation in the edge table
boolean hasResourceRelation(Resource resource, ResourceRelation relation) {
return checkEdgeExistence(resource, relation, 0);
}
// Checks whether or not a given resource has any direct children
boolean hasChildren(Resource parent, ResourceRelation relation) {
return checkEdgeExistence(parent, relation, 1);
}
// Checks whether or not resource(s) in the edge table exist based on
// relation and distance from the given resource
private boolean checkEdgeExistence(Resource resource, ResourceRelation relation, int distance) {
String hql = "select count(re) from ResourceEdge re "
+ "where re.from=:from and distance=:distance and relation=:relation";
int result = ((Number) getSession().createQuery(hql).setParameter("from", resource)
.setParameter("relation", relation).setInteger("distance", distance).iterate().next())
.intValue();
return result > 0;
}
boolean isResourceChildOf(Resource parent, Resource child) {
String sql = "from ResourceEdge re "
+ "where re.from=:from and re.to=:to and distance=:distance and rel_id=:rel_id";
// ...in most cases we want to check for a direct parent child
// relationship
int distance = 1;
if (parent.getResourceType().getAppdefType() == AppdefEntityConstants.APPDEF_TYPE_PLATFORM &&
child.getResourceType().getAppdefType() == AppdefEntityConstants.APPDEF_TYPE_SERVICE) {
// ...in the case where the parent is a platform and the child is a
// service, we need to adjust the distance
// to get the appropriate answer...
distance = 2;
}
List results = getSession().createQuery(sql).setParameter("from", parent).setParameter(
"to", child).setInteger("distance", distance).setInteger("rel_id",
AuthzConstants.RELATION_CONTAINMENT_ID.intValue()).list();
return results.size() == 1;
}
}